﻿//-----------------------------------------------------------------------
// <copyright>
//     Copyright (c) Artur Mustafin. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

using System;
using Excel.Expressions.Classes;
using Excel.Expressions.Compiler;
using Expressions.Compiler;

namespace Excel.Expressions
{
    internal static partial class Expressions
    {
        // Forward declarations
        internal static Expression<char, CellExpression> cell_assigment_expression = "cell-assigment-expression[t]";
        internal static Expression<char, CellExpression> cell_reference = "cell-reference[t]";
        internal static Expression<char, CellExpression> cell_reference_group = "cell-reference-group[t]";
        internal static Expression<char, CellExpression> cell_expression = "cell-expression[t]";
        internal static Expression<char, CellExpression> cell_expression_parameters = "cell-expression-paremeters[t]";
        internal static Expression<char, CellExpression> cell_function_definition = "cell-function-definition[t]";
        internal static Expression<char, CellExpression> cell_function_arg = "cell-function-arg[t]";
        internal static Expression<char, CellExpression> cell_function_arg_list = "cell-function-arg-list[t]";
        internal static Expression<char, CellExpression> cell_function_arg_list_part = "cell-function-arg-list-part[t]";
        internal static Expression<char, CellExpression> E = "E[t]";
        internal static Expression<char, CellExpression> Eopt = "E'[t]";
        internal static Expression<char, CellExpression> T = "T[t]";
        internal static Expression<char, CellExpression> Topt = "T'[t]";
        internal static Expression<char, CellExpression> F = "F[t]";

        static Expressions()
        {
            E.Eval = _E();
            T.Eval = _T();
            Eopt.Eval = _Eopt();
            Topt.Eval = _Topt();
            F.Eval = _F();
            cell_expression.Eval = _cell_expression();
            cell_expression_parameters.Eval = _cell_expression_parameters();
            cell_assigment_expression.Eval = _cell_assigment_expression();
            cell_function_definition.Eval = _cell_function_definition();
            cell_function_arg.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(Nonterminals.E))
                {
                    return E[a, b[0]];
                }
                if (b[0].Context.Token.Equals(Nonterminals.cell_reference_group))
                {
                    return cell_reference_group[a, b[0]];
                }
                throw new NotSupportedException("Input token is not supported");
            };
            cell_function_arg_list.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(Nonterminals.cell_function_arg) && (b[1] == null || b[1].Context.Token.Equals(Nonterminals.cell_function_arg_list_part)))
                {
                    return new Parameter(cell_function_arg[a, b[0]], cell_function_arg_list_part[a, b[1]]);
                }
                throw new NotSupportedException("Input token is not supported");
            };
            cell_function_arg_list_part.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(',') && b[1].Context.Token.Equals(Nonterminals.cell_function_arg_list))
                {
                    return cell_function_arg_list[a, b[1]];
                }
                throw new NotSupportedException("Input token is not supported");
            };
            cell_reference_group.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(Nonterminals.cell_reference) && b[1].Context.Token.Equals(':') && b[2].Context.Token.Equals(Nonterminals.cell_reference))
                {
                    return new CellReferenceGroup(cell_reference[a, b[0]], cell_reference[a, b[2]]);
                }
                throw new NotSupportedException("Input token is not supported");
            };
            cell_reference.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(Nonterminals.alpha_digits) && b[1].Context.Token.Equals(Nonterminals.decimal_digits))
                {
                    return new CellReference(Cell.GetRow(b[0].Context.ToString()), Cell.GetCol(b[1].Context.ToString()));
                }
                throw new NotSupportedException("Input token is not supported");
            };
        }
    }
}